#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
主应用模块
"""

import os
import sys
from datetime import datetime
from PyQt5.QtWidgets import (
    QMainWindow, QPushButton, QVBoxLayout, QHBoxLayout, 
    QWidget, QLabel, QFileDialog, QMessageBox, QComboBox, QSpinBox,
    QCheckBox, QGroupBox, QProgressBar, QSystemTrayIcon, QMenu, QAction,
    QStyle, QSizePolicy, QApplication
)
from PyQt5.QtCore import Qt, pyqtSignal, QTimer, QSize
from PyQt5.QtGui import QImage, QPixmap, QIcon, QKeySequence, QPainter, QColor

from modules.recorder import ScreenRecorderThread, RecordingTimer
from modules.floatball import FloatBall
from modules.utils import (
    format_time, generate_output_filename, get_default_save_directory,
    get_file_size_str, resource_path
)

class ScreenRecorderApp(QMainWindow):
    """录屏软件主窗口类"""
    def __init__(self):
        super().__init__()
        self.output_file = None
        self.recorder_thread = None
        self.timer_thread = None
        self.recording_duration = 0
        self.tray_icon = None
        self.float_ball = None
        
        # 初始化UI
        self.init_ui()
        
        # 设置系统托盘
        self.setup_tray_icon()
        
        # 设置快捷键
        self.setup_shortcuts()
        
        # 设置悬浮球
        self.setup_float_ball()
        
        # 设置应用图标
        self.setWindowIcon(self.style().standardIcon(QStyle.SP_ComputerIcon))
        
        # 检测显示器
        self.detect_monitors()
        
        # 设置默认保存路径
        self.set_default_save_path()

    def init_ui(self):
        """初始化用户界面"""
        self.setWindowTitle("mars录屏")
        self.setGeometry(100, 100, 600, 500)
        self.setMinimumSize(500, 400)

        # 创建主布局
        central_widget = QWidget()
        main_layout = QVBoxLayout(central_widget)
        self.setCentralWidget(central_widget)

        # 添加标题标签
        title_label = QLabel("mars录屏")
        title_label.setAlignment(Qt.AlignCenter)
        title_label.setStyleSheet("font-size: 20pt; font-weight: bold; margin: 10px;")
        main_layout.addWidget(title_label)

        # 添加设置区域
        settings_group = QGroupBox("录制设置")
        settings_layout = QVBoxLayout(settings_group)
        
        # 添加文件路径设置
        path_layout = QHBoxLayout()
        path_layout.addWidget(QLabel("保存路径:"))
        self.path_label = QLabel("未选择保存路径")
        self.path_label.setStyleSheet("color: gray; font-style: italic;")
        self.path_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        path_layout.addWidget(self.path_label)
        self.select_path_btn = QPushButton("选择路径")
        self.select_path_btn.clicked.connect(self.select_output_path)
        path_layout.addWidget(self.select_path_btn)
        settings_layout.addLayout(path_layout)
        
        # 添加显示器选择
        monitor_layout = QHBoxLayout()
        monitor_layout.addWidget(QLabel("录制显示器:"))
        self.monitor_combo = QComboBox()
        self.monitor_combo.addItem("主显示器")  # 默认选项
        monitor_layout.addWidget(self.monitor_combo)
        settings_layout.addLayout(monitor_layout)
        
        # 添加帧率设置
        fps_layout = QHBoxLayout()
        fps_layout.addWidget(QLabel("帧率:"))
        self.fps_spin = QSpinBox()
        self.fps_spin.setRange(1, 60)
        self.fps_spin.setValue(15)
        self.fps_spin.setSuffix(" FPS")
        fps_layout.addWidget(self.fps_spin)
        
        # 添加音频录制选项
        self.audio_checkbox = QCheckBox("录制系统音频")
        fps_layout.addWidget(self.audio_checkbox)
        
        # 添加悬浮球选项
        self.float_ball_checkbox = QCheckBox("显示悬浮球")
        self.float_ball_checkbox.setChecked(True)
        self.float_ball_checkbox.stateChanged.connect(self.toggle_float_ball)
        fps_layout.addWidget(self.float_ball_checkbox)
        
        settings_layout.addLayout(fps_layout)
        
        main_layout.addWidget(settings_group)

        # 添加状态区域
        status_group = QGroupBox("录制状态")
        status_layout = QVBoxLayout(status_group)
        
        # 添加状态标签
        self.status_label = QLabel("就绪")
        self.status_label.setAlignment(Qt.AlignCenter)
        self.status_label.setStyleSheet("color: green; font-size: 14pt; font-weight: bold;")
        status_layout.addWidget(self.status_label)
        
        # 添加录制时间显示
        time_layout = QHBoxLayout()
        time_layout.addWidget(QLabel("录制时间:"))
        self.time_label = QLabel("00:00:00")
        self.time_label.setStyleSheet("font-size: 12pt; font-family: monospace;")
        time_layout.addWidget(self.time_label)
        status_layout.addLayout(time_layout)
        
        # 添加进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setTextVisible(False)
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        self.progress_bar.setStyleSheet("""
            QProgressBar {
                border: 1px solid grey;
                border-radius: 5px;
                text-align: center;
            }
            QProgressBar::chunk {
                background-color: #05B8CC;
                width: 10px;
                margin: 0.5px;
            }
        """)
        status_layout.addWidget(self.progress_bar)
        
        main_layout.addWidget(status_group)

        # 添加按钮布局
        btn_layout = QHBoxLayout()

        # 添加开始录制按钮
        self.start_btn = QPushButton("开始录制")
        self.start_btn.setStyleSheet("""
            QPushButton {
                background-color: #4CAF50;
                color: white;
                font-size: 14pt;
                padding: 10px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
            QPushButton:disabled {
                background-color: #cccccc;
            }
        """)
        self.start_btn.clicked.connect(self.start_recording)
        btn_layout.addWidget(self.start_btn)

        # 添加暂停/恢复按钮
        self.pause_btn = QPushButton("暂停录制")
        self.pause_btn.setStyleSheet("""
            QPushButton {
                background-color: #FF9800;
                color: white;
                font-size: 14pt;
                padding: 10px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #F57C00;
            }
            QPushButton:disabled {
                background-color: #cccccc;
            }
        """)
        self.pause_btn.clicked.connect(self.toggle_pause_recording)
        self.pause_btn.setEnabled(False)  # 初始时禁用
        btn_layout.addWidget(self.pause_btn)

        # 添加停止录制按钮
        self.stop_btn = QPushButton("停止录制")
        self.stop_btn.setStyleSheet("""
            QPushButton {
                background-color: #f44336;
                color: white;
                font-size: 14pt;
                padding: 10px;
                border-radius: 5px;
            }
            QPushButton:hover {
                background-color: #d32f2f;
            }
            QPushButton:disabled {
                background-color: #cccccc;
            }
        """)
        self.stop_btn.clicked.connect(self.stop_recording)
        self.stop_btn.setEnabled(False)  # 初始时禁用
        btn_layout.addWidget(self.stop_btn)

        main_layout.addLayout(btn_layout)

        # 添加预览区域
        preview_group = QGroupBox("预览")
        preview_layout = QVBoxLayout(preview_group)
        self.preview_label = QLabel("预览区域")
        self.preview_label.setAlignment(Qt.AlignCenter)
        self.preview_label.setStyleSheet("border: 1px solid #cccccc; background-color: #f0f0f0;")
        self.preview_label.setMinimumHeight(150)
        preview_layout.addWidget(self.preview_label)
        main_layout.addWidget(preview_group)
        
        # 添加快捷键提示
        shortcut_label = QLabel("快捷键: F9 = 开始/停止录制, F10 = 暂停/恢复, Esc = 退出")
        shortcut_label.setAlignment(Qt.AlignCenter)
        shortcut_label.setStyleSheet("color: gray; font-style: italic;")
        main_layout.addWidget(shortcut_label)

    def setup_shortcuts(self):
        """设置键盘快捷键"""
        # F9 开始/停止录制
        self.record_shortcut = QKeySequence("F9")
        self.record_action = QAction("开始/停止录制", self)
        self.record_action.setShortcut(self.record_shortcut)
        self.record_action.triggered.connect(self.toggle_recording)
        self.addAction(self.record_action)
        
        # F10 暂停/恢复录制
        self.pause_shortcut = QKeySequence("F10")
        self.pause_action = QAction("暂停/恢复录制", self)
        self.pause_action.setShortcut(self.pause_shortcut)
        self.pause_action.triggered.connect(self.toggle_pause_recording)
        self.addAction(self.pause_action)
        
        # Esc 退出应用
        self.exit_shortcut = QKeySequence("Esc")
        self.exit_action = QAction("退出", self)
        self.exit_action.setShortcut(self.exit_shortcut)
        self.exit_action.triggered.connect(self.close)
        self.addAction(self.exit_action)

    def setup_tray_icon(self):
        """设置系统托盘图标"""
        try:
            self.tray_icon = QSystemTrayIcon(self)
            self.tray_icon.setIcon(self.style().standardIcon(QStyle.SP_ComputerIcon))
            
            # 创建托盘菜单
            tray_menu = QMenu()
            
            # 添加显示/隐藏动作
            show_action = QAction("显示主窗口", self)
            show_action.triggered.connect(self.show_and_activate)
            tray_menu.addAction(show_action)
            
            # 添加开始/停止录制动作
            self.tray_record_action = QAction("开始录制", self)
            self.tray_record_action.triggered.connect(self.toggle_recording)
            tray_menu.addAction(self.tray_record_action)
            
            # 添加暂停/恢复录制动作
            self.tray_pause_action = QAction("暂停录制", self)
            self.tray_pause_action.triggered.connect(self.toggle_pause_recording)
            self.tray_pause_action.setEnabled(False)
            tray_menu.addAction(self.tray_pause_action)
            
            # 添加显示/隐藏悬浮球动作
            self.tray_float_action = QAction("显示悬浮球", self)
            self.tray_float_action.triggered.connect(self.toggle_float_ball_from_tray)
            tray_menu.addAction(self.tray_float_action)
            
            # 添加退出动作
            quit_action = QAction("退出", self)
            quit_action.triggered.connect(QApplication.quit)
            tray_menu.addAction(quit_action)
            
            # 设置托盘菜单
            self.tray_icon.setContextMenu(tray_menu)
            self.tray_icon.show()
            
            # 连接托盘图标点击事件
            self.tray_icon.activated.connect(self.tray_icon_activated)
        except Exception as e:
            print(f"系统托盘初始化失败: {str(e)}")

    def setup_float_ball(self):
        """设置悬浮球"""
        try:
            self.float_ball = FloatBall()
            
            # 连接悬浮球信号
            self.float_ball.start_recording.connect(self.start_recording)
            self.float_ball.stop_recording.connect(self.stop_recording)
            self.float_ball.pause_recording.connect(self.pause_recording)
            self.float_ball.resume_recording.connect(self.resume_recording)
            self.float_ball.show_main_window.connect(self.show_and_activate)
            
            # 默认显示悬浮球
            self.float_ball.show()
        except Exception as e:
            print(f"悬浮球初始化失败: {str(e)}")
            self.float_ball = None
            self.float_ball_checkbox.setChecked(False)
            self.float_ball_checkbox.setEnabled(False)

    def show_and_activate(self):
        """显示并激活窗口"""
        self.show()
        self.activateWindow()
        self.raise_()

    def toggle_float_ball(self, state):
        """切换悬浮球显示状态"""
        if self.float_ball:
            if state == Qt.Checked:
                self.float_ball.show()
                if self.tray_float_action:
                    self.tray_float_action.setText("隐藏悬浮球")
            else:
                self.float_ball.hide()
                if self.tray_float_action:
                    self.tray_float_action.setText("显示悬浮球")

    def toggle_float_ball_from_tray(self):
        """从托盘菜单切换悬浮球显示状态"""
        if self.float_ball:
            if self.float_ball.isVisible():
                self.float_ball.hide()
                self.float_ball_checkbox.setChecked(False)
                self.tray_float_action.setText("显示悬浮球")
            else:
                self.float_ball.show()
                self.float_ball_checkbox.setChecked(True)
                self.tray_float_action.setText("隐藏悬浮球")

    def tray_icon_activated(self, reason):
        """托盘图标被激活时的处理"""
        if reason == QSystemTrayIcon.DoubleClick:
            self.show_and_activate()

    def detect_monitors(self):
        """检测系统显示器"""
        try:
            import mss
            with mss.mss() as sct:
                self.monitor_combo.clear()
                for i, monitor in enumerate(sct.monitors[1:], 1):  # 跳过第一个（全部显示器）
                    width, height = monitor["width"], monitor["height"]
                    self.monitor_combo.addItem(f"显示器 {i} ({width}x{height})", i)
        except Exception as e:
            print(f"检测显示器失败: {str(e)}")
            self.monitor_combo.clear()
            self.monitor_combo.addItem("主显示器", 1)

    def set_default_save_path(self):
        """设置默认保存路径"""
        try:
            default_dir = get_default_save_directory()
            default_file = os.path.join(default_dir, generate_output_filename())
            self.output_file = default_file
            self.path_label.setText(default_file)
            self.path_label.setStyleSheet("color: blue;")
        except Exception as e:
            print(f"设置默认保存路径失败: {str(e)}")

    def select_output_path(self):
        """选择视频保存路径"""
        # 生成默认文件名 (基于当前时间)
        default_filename = generate_output_filename()
        default_dir = os.path.dirname(self.output_file) if self.output_file else get_default_save_directory()
        
        file_path, _ = QFileDialog.getSaveFileName(
            self, "保存视频", os.path.join(default_dir, default_filename), "MP4 Files (*.mp4);;All Files (*)"
        )
        if file_path:
            self.output_file = file_path
            self.path_label.setText(file_path)
            self.path_label.setStyleSheet("color: blue;")

    def toggle_recording(self):
        """切换录制状态"""
        if self.recorder_thread and self.recorder_thread.isRunning():
            self.stop_recording()
        else:
            self.start_recording()

    def toggle_pause_recording(self):
        """切换暂停/恢复状态"""
        if not self.recorder_thread or not self.recorder_thread.isRunning():
            return
            
        if self.recorder_thread.is_paused():
            self.resume_recording()
        else:
            self.pause_recording()

    def start_recording(self):
        """开始录制"""
        if not self.output_file:
            QMessageBox.warning(self, "警告", "请先选择保存路径")
            return

        # 检查文件是否已存在
        if os.path.exists(self.output_file):
            reply = QMessageBox.question(
                self, "确认", "文件已存在，是否覆盖？", QMessageBox.Yes | QMessageBox.No
            )
            if reply == QMessageBox.No:
                return

        # 获取设置
        fps = self.fps_spin.value()
        monitor_idx = self.monitor_combo.currentData()
        record_audio = self.audio_checkbox.isChecked()
        
        # 创建录制线程
        self.recorder_thread = ScreenRecorderThread(
            self.output_file, 
            fps=fps, 
            preview=True, 
            monitor_num=monitor_idx,
            record_audio=record_audio
        )
        
        # 连接信号
        self.recorder_thread.recording_stopped.connect(self.on_recording_stopped)
        self.recorder_thread.update_frame.connect(self.update_preview)
        self.recorder_thread.recording_error.connect(self.on_recording_error)
        self.recorder_thread.recording_progress.connect(self.update_progress_bar)
        
        # 创建计时器线程
        self.timer_thread = RecordingTimer()
        self.timer_thread.update_time.connect(self.update_recording_time)
        
        # 开始录制和计时
        self.recorder_thread.start()
        self.timer_thread.start()
        
        # 更新UI状态
        self.status_label.setText("正在录制...")
        self.status_label.setStyleSheet("color: red; font-size: 14pt; font-weight: bold;")
        self.start_btn.setEnabled(False)
        self.pause_btn.setEnabled(True)
        self.stop_btn.setEnabled(True)
        self.select_path_btn.setEnabled(False)
        self.fps_spin.setEnabled(False)
        self.monitor_combo.setEnabled(False)
        self.audio_checkbox.setEnabled(False)
        
        # 更新托盘图标
        if self.tray_icon:
            self.tray_icon.setToolTip("mars录屏 - 正在录制")
            self.tray_record_action.setText("停止录制")
            self.tray_pause_action.setEnabled(True)
            self.tray_pause_action.setText("暂停录制")
            
        # 更新悬浮球状态
        if self.float_ball:
            self.float_ball.set_recording_state(True, False)
            
        # 显示通知
        if self.tray_icon:
            self.tray_icon.showMessage("录制开始", "屏幕录制已开始", QSystemTrayIcon.Information, 2000)

    def pause_recording(self):
        """暂停录制"""
        if self.recorder_thread and self.recorder_thread.isRunning():
            self.recorder_thread.pause()
            self.status_label.setText("录制已暂停")
            self.status_label.setStyleSheet("color: orange; font-size: 14pt; font-weight: bold;")
            self.pause_btn.setText("恢复录制")
            
            # 更新托盘图标
            if self.tray_icon:
                self.tray_icon.setToolTip("mars录屏 - 录制已暂停")
                self.tray_pause_action.setText("恢复录制")
            
            # 更新悬浮球状态
            if self.float_ball:
                self.float_ball.set_recording_state(True, True)
                
            # 暂停计时器
            if self.timer_thread and self.timer_thread.isRunning():
                self.timer_thread.stop()

    def resume_recording(self):
        """恢复录制"""
        if self.recorder_thread and self.recorder_thread.isRunning():
            self.recorder_thread.resume()
            self.status_label.setText("正在录制...")
            self.status_label.setStyleSheet("color: red; font-size: 14pt; font-weight: bold;")
            self.pause_btn.setText("暂停录制")
            
            # 更新托盘图标
            if self.tray_icon:
                self.tray_icon.setToolTip("mars录屏 - 正在录制")
                self.tray_pause_action.setText("暂停录制")
            
            # 更新悬浮球状态
            if self.float_ball:
                self.float_ball.set_recording_state(True, False)
                
            # 重新启动计时器
            if not self.timer_thread or not self.timer_thread.isRunning():
                self.timer_thread = RecordingTimer()
                self.timer_thread.update_time.connect(self.update_recording_time)
                self.timer_thread.seconds = self.recording_duration
                self.timer_thread.start()

    def stop_recording(self):
        """停止录制"""
        if self.recorder_thread and self.recorder_thread.isRunning():
            self.recorder_thread.stop()
            if self.timer_thread and self.timer_thread.isRunning():
                self.timer_thread.stop()
            self.status_label.setText("正在保存...")
            self.status_label.setStyleSheet("color: orange; font-size: 14pt; font-weight: bold;")
            
            # 更新托盘图标
            if self.tray_icon:
                self.tray_icon.setToolTip("mars录屏 - 正在保存")
                self.tray_pause_action.setEnabled(False)
            
            # 更新悬浮球状态
            if self.float_ball:
                self.float_ball.set_recording_state(False)

    def on_recording_stopped(self):
        """录制停止后的处理"""
        self.status_label.setText("录制完成")
        self.status_label.setStyleSheet("color: green; font-size: 14pt; font-weight: bold;")
        self.start_btn.setEnabled(True)
        self.pause_btn.setEnabled(False)
        self.pause_btn.setText("暂停录制")
        self.stop_btn.setEnabled(False)
        self.select_path_btn.setEnabled(True)
        self.fps_spin.setEnabled(True)
        self.monitor_combo.setEnabled(True)
        self.audio_checkbox.setEnabled(True)
        
        # 更新托盘图标
        if self.tray_icon:
            self.tray_icon.setToolTip("mars录屏")
            self.tray_record_action.setText("开始录制")
            self.tray_pause_action.setEnabled(False)
            self.tray_pause_action.setText("暂停录制")
            
            # 显示通知
            file_size = get_file_size_str(self.output_file)
            self.tray_icon.showMessage(
                "录制完成", 
                f"录制已完成并保存至:\n{self.output_file}\n大小: {file_size}", 
                QSystemTrayIcon.Information, 
                3000
            )
        
        # 显示录制完成消息
        duration_str = self.time_label.text()
        file_size = get_file_size_str(self.output_file)
        QMessageBox.information(
            self, 
            "完成", 
            f"录制已完成并保存至:\n{self.output_file}\n\n录制时长: {duration_str}\n文件大小: {file_size}"
        )
        
        # 重置进度条和时间显示
        self.progress_bar.setValue(0)
        
        # 生成新的默认文件名
        self.set_default_save_path()

    def on_recording_error(self, error_msg):
        """处理录制错误"""
        QMessageBox.critical(self, "录制错误", error_msg)
        self.stop_recording()

    def update_recording_time(self, seconds):
        """更新录制时间显示"""
        self.recording_duration = seconds
        time_str = format_time(seconds)
        self.time_label.setText(time_str)

    def update_progress_bar(self, seconds):
        """更新进度条"""
        # 进度条显示录制时长，每小时为一个周期
        progress = (seconds % 3600) / 36  # 0-100
        self.progress_bar.setValue(int(progress))

    def update_preview(self, frame):
        """更新预览画面"""
        try:
            import cv2
            # 调整帧大小以适应预览区域
            h, w, c = frame.shape
            preview_w = self.preview_label.width()
            preview_h = self.preview_label.height()
            
            # 保持宽高比
            aspect_ratio = w / h
            if preview_w / preview_h > aspect_ratio:
                new_w = int(preview_h * aspect_ratio)
                new_h = preview_h
            else:
                new_w = preview_w
                new_h = int(preview_w / aspect_ratio)
            
            # 调整大小
            resized_frame = cv2.resize(frame, (new_w, new_h))
            
            # 转换为QImage并显示
            bytes_per_line = 3 * new_w
            q_img = QImage(resized_frame.data, new_w, new_h, bytes_per_line, QImage.Format_RGB888).rgbSwapped()
            self.preview_label.setPixmap(QPixmap.fromImage(q_img))
        except Exception as e:
            print(f"更新预览失败: {str(e)}")

    def closeEvent(self, event):
        """窗口关闭事件处理"""
        if self.recorder_thread and self.recorder_thread.isRunning():
            reply = QMessageBox.question(
                self, "确认", "录制正在进行中，确定要最小化到托盘吗？", 
                QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel,
                QMessageBox.No
            )
            
            if reply == QMessageBox.Cancel:
                event.ignore()
                return
            elif reply == QMessageBox.Yes:
                # 最小化到托盘
                self.hide()
                if self.tray_icon:
                    self.tray_icon.showMessage(
                        "录制继续中", 
                        "应用已最小化到系统托盘，录制继续进行",
                        QSystemTrayIcon.Information, 
                        2000
                    )
                event.ignore()
                return
            else:
                # 用户选择退出
                self.recorder_thread.stop()
                if self.timer_thread:
                    self.timer_thread.stop()
                self.recorder_thread.wait()
                event.accept()
        else:
            # 没有录制时直接最小化到托盘
            self.hide()
            event.ignore()

    def hideEvent(self, event):
        """窗口隐藏事件处理"""
        # 总是最小化到托盘，不真正隐藏
        if self.tray_icon and self.tray_icon.isVisible():
            if self.recorder_thread and self.recorder_thread.isRunning():
                self.tray_icon.showMessage(
                    "录制继续中", 
                    "应用已最小化到系统托盘，录制继续进行",
                    QSystemTrayIcon.Information, 
                    2000
                )
        event.accept()